﻿using System;
using System.Text;
using System.Web.UI;
using Ext.Net;

namespace KamLib
{

    public class StoreLogicContainer : EquipContainer, IStoreContainer
    {
        public StoreLogicContainer(ListLogic logic) { Logic = logic; }
        public ListLogic Logic;

        public Store Store { get; set; }
        public string GroupField { get { return Logic.GroupField; } }
        public string KeyField { get { return Logic.KeyField; } }
        public string SortField { get { return Logic.SortField; } }
        public SortDirection SortDir { get { return Logic.SortDir; } }
    }

    public class GridLogicContainer : EquipContainer, IGridContainer, IListLogicContainer
    {
        public GridLogicContainer(ListLogic logic) { Logic = logic; }
        public ListLogic Logic { get; set; }

        public GridPanel Grid { get; set; }
        public EntityDescAttribute EntityDesc { get { return Logic.EntityDesc; } }
        public bool IsLocal { get { return Logic.IsLocal; } }
        public bool CanEdit { get { return Logic.CanEdit; } }
        public bool CanDelete { get { return Logic.CanDelete; } }
        public bool CanInsert { get { return Logic.CanInsert; } }
        public int PageSize { get { return Logic.PageSize; } }
        public object cmdAdd { get; set; }

        public void Initialize() { }
    }

    public static class GridLogicAdapter
    {

        public static void Apply(ListLogic logic, IGridContainer c)
        {
            var grid = c.Grid;
            var klGrid = grid as Controls.Grid;
            if (klGrid != null)
                klGrid.Logic = logic;

            var isPreRendered = false;
            grid.PreRender += (sender, e) =>
            {
                if (isPreRendered) return;
                isPreRendered = true;
                grid.Listeners.AfterRender.Handler += "KamLib.Logic.Grid.register(" + logic.Key + ", " + 
                    (logic.IsLocal ? "true" : "false") +
                    ", {grid:this, virtualPath:'" + logic.Controller.VirtualPath + "'});";
                grid.Listeners.BeforeDestroy.Handler += "KamLib.Logic.Grid.unregister(this);";
            };
            if (c.IsLocal)
            {
                foreach (var col in c.Grid.ColumnModel.Columns)
                    col.MenuDisabled = true;
            }

            var istore = c.Owner.Get<IStoreContainer>();
            if (istore == null) return;

            var store = istore.Store;
            logic.AddFields(istore);

            if (c.IsLocal) return;


            store.Proxy.Add(new HttpProxy
            {
                Json = true,
                Headers = { new Parameter { Name = "X-Ext.Net", Value = "delta=true" } },
                Url = logic.Controller.VirtualPath + "Service.asmx/ListSelect",
            });
            store.Listeners.BeforeLoad.Handler += "options.params.key=Ext.encode(" + grid.ClientID + "._biKey);options.params.group=this.groupField||null;";
        }

        public static GridLogicContainer Apply(Control parent, ListLogic logic, GridPanel grid)
        {
            if (logic.Key == null)
                logic.Key = new UiKey(logic);

            if (logic.Creating)
            {
                var gc = new GridLogicContainer(logic) { Grid = grid };
                gc.Owner.Register(new StoreLogicContainer(logic));
                logic.EquipContainer = gc.Owner;

                GridEquiper.Apply(gc);
                Apply(logic, gc);
                logic.EquipingControl(parent, gc);


                return gc;
            }

            return null;
        }
    }


    public static class FormGridLogicAdapter
    {
        public static void Apply(ListLogic listLogic, UiFormLogicNodeInfo formLogicNode, IGridContainer c)
        {
            if (listLogic == null || formLogicNode == null || c == null) return;
            var grid = c.Grid;

            var isPreRendered = false;
            grid.PreRender += (sender, e) =>
            {
                if (isPreRendered) return;
                isPreRendered = true;
                if (formLogicNode.KeyFields == null) return;
                if (listLogic.KeyFields.Length != formLogicNode.KeyFields.Length) return;

                var sb = new StringBuilder();
                sb.Append(@"this._biLItem.getIdOfForm=function(rec){return !rec.data?{""");
                sb.Append(formLogicNode.KeyFields[0]);
                sb.Append(@""":rec.id}:{");
                for (var i = 0; i < listLogic.KeyFields.Length; ++i)
                {
                    if (i > 0) sb.Append(',');
                    sb.AppendFormat(@"""{0}"":rec.data['{1}']", formLogicNode.KeyFields[i], listLogic.KeyFields[i]);
                }
                sb.AppendLine("}};");
                sb.AppendLine(@"this._biLItem.getIdOfGrid=function(key){return key.id?key.id['" + formLogicNode.KeyFields[0] + "']:null};");

                grid.Listeners.AfterRender.Handler += sb.ToString();
            };

            grid.Listeners.Command.Handler =
                "KamLib.Logic.Grid.execFormCommand('" + formLogicNode.Node.LID +
                "', '" + formLogicNode.LIID + "', this, record, command);";

            if (listLogic.CanInsert && c.cmdAdd != null)
            {
                var click =
                    "KamLib.Logic.Grid.execFormCommand('" + formLogicNode.Node.LID +
                    "', '" + formLogicNode.LIID + "', " + grid.ClientID + ", null, 'add');";
                if (c.cmdAdd is Button)
                    ((Button)c.cmdAdd).OnClientClick += click;
                else if (c.cmdAdd is Tool)
                    ((Tool)c.cmdAdd).Handler += click;
            }
            if (listLogic.CanEdit)
            {
                grid.Listeners.RowDblClick.Handler +=
                    "KamLib.Logic.Grid.execFormCommand('" + formLogicNode.Node.LID +
                    "', '" + formLogicNode.LIID + "', " + grid.ClientID + ", this.store.getAt(rowIndex), 'edit');";
            }
        }
    }



    public abstract class GridLogicControl : LogicControl, IListLogicContainer
    {
        public new ListLogic Logic { get { return (ListLogic)base.Logic; } set { base.Logic = value; } }

        public EquipInterfaceContainer Owner { get { return gc.Owner; } set { } }

        private bool _initialized;
        private GridLogicContainer gc;
        public override void Initialize()
        {
            if (_initialized) return;
            _initialized = true;

            if (Logic == null)
            {
                var lc = this.Parent<LogicPanel>();
                if (lc == null || lc.LogicNode == null || lc.LogicNode.ListInfos.Count == 0) return;
                Logic = lc.LogicNode.GetList();
            }

            var grid = FindControl("Grid") as GridPanel;
            if (grid == null)
                throw new Exception("Can't find GridPanel with id 'Grid' on '" + ClientID + "'.");

            gc = GridLogicAdapter.Apply(this, Logic, grid);

            base.Initialize();
        }

    }

}